package com.cke.yang.security.domain.repository.impl;

import com.cke.yang.common.infra.enums.SaveActionEnum;
import com.cke.yang.common.domain.model.SecUserDetails;
import com.cke.yang.common.infra.utils.UserDetailsUtils;
import com.cke.yang.security.api.dto.request.SecUserListRequest;
import com.cke.yang.security.domain.entity.SecUser;
import com.cke.yang.security.domain.repository.SecUserRepository;
import com.cke.yang.security.infra.mapper.SecUserMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Repository;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;

/**
 * 用户
 *
 * @author yuyang
 */
@Slf4j
@Repository
public class SecUserRepositoryImpl implements SecUserRepository {

    @Value("${security.user.password:123456}")
    private String defaultPassword;
    @Resource
    private SecUserMapper secUserMapper;
    @Resource
    private PasswordEncoder passwordEncoder;

    @Override
    public List<SecUser> list(SecUserListRequest param) {
        LambdaQueryWrapper<SecUser> queryWrapper = new LambdaQueryWrapper<>();
        // 此处将param里参数转换为queryWrapper的参数表达形式
        queryWrapper
                .like(param.getUsername() != null, SecUser::getUsername, param.getUsername());
        return this.secUserMapper.selectList(queryWrapper);
    }

    @Override
    public SecUser save(SaveActionEnum action, SecUser secUser) {
        switch (action) {
            case INSERT:
                initSecUser(secUser);
                secUserMapper.insert(secUser);
                break;
            case UPDATE:
                protectSomeFields(secUser);
                secUserMapper.updateById(secUser);
                break;
            case DELETE:
                secUserMapper.deleteById(secUser);
                break;
            default:
                log.info("不受支持的数据操作 {}", action);
        }
        return secUser;
    }

    @Override
    public Optional<UserDetails> findByUsername(String username) {
        SecUser secUser = this.secUserMapper.selectOne(new LambdaQueryWrapper<SecUser>().eq(SecUser::getUsername, username));
        return Optional.ofNullable(Objects.nonNull(secUser) ? new SecUserDetails(secUser) : null);
    }

    @Override
    public SecUser findById(Long userId) {
        return this.secUserMapper.selectById(userId);
    }

    @Override
    public void updatePassword(Long userId, String encodedPassword) {
        SecUser secUser = new SecUser();
        secUser.setUserId(userId);
        secUser.setPassword(encodedPassword);

        // 设置审计信息
        SecUserDetails details = UserDetailsUtils.getCurrentUserDetails();
        if (Objects.nonNull(details)) {
            secUser.setLastUpdatedBy(details.getUserId());
            secUser.setLastUpdatedAt(new Date());
        }

        this.secUserMapper.updateById(secUser);
    }

    private void protectSomeFields(SecUser secUser) {
        SecUser oldUser = this.secUserMapper.selectById(secUser.getUserId());
        // 不允许在更新的时候修改密码和openId
        secUser.setPassword(oldUser.getPassword());
        secUser.setOpenId(oldUser.getOpenId());
        // 审计字段赋值
        SecUserDetails details = UserDetailsUtils.getCurrentUserDetails();
        if (Objects.nonNull(details)) {
            secUser.setLastUpdatedBy(details.getUserId());
            secUser.setLastUpdatedAt(new Date());
        }
    }

    private void initSecUser(SecUser secUser) {
        // openId 取uuid
        secUser.setOpenId(UUID.randomUUID().toString().replace("-", ""));
        // 基于 BCryptPasswordEncoder 进行密码加密
        secUser.setPassword(passwordEncoder.encode(defaultPassword));
        // 审计信息
        SecUserDetails details = UserDetailsUtils.getCurrentUserDetails();
        if (Objects.nonNull(details)) {
            secUser.setCreatedBy(details.getUserId());
            secUser.setCreatedAt(new Date());
            secUser.setLastUpdatedBy(details.getUserId());
            secUser.setLastUpdatedAt(new Date());
        }
    }

    private String encodePassword(String rawPassword) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] hashBytes = digest.digest(rawPassword.getBytes(StandardCharsets.UTF_8));
            StringBuilder hexString = new StringBuilder();
            for (byte b : hashBytes) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) {
                    hexString.append('0');
                }
                hexString.append(hex);
            }
            return hexString.toString();
        } catch (NoSuchAlgorithmException e) {
            log.error("生成密码哈希时出错", e);
            throw new RuntimeException(e);
        }
    }

}
